"""
FastAPI 服务主程序
"""
import os
import sys
from pathlib import Path
from typing import Optional
from datetime import datetime

from fastapi import FastAPI, File, UploadFile, HTTPException, Form
from fastapi.responses import HTMLResponse, JSONResponse
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware
from pydantic import BaseModel, Field
from loguru import logger

from config import settings
from model_manager import model_manager
from face.face_detector import face_detector

# 配置日志
logger.remove()
logger.add(
    sys.stderr,
    format="<green>{time:YYYY-MM-DD HH:mm:ss}</green> | <level>{level: <8}</level> | <cyan>{name}</cyan>:<cyan>{function}</cyan> - <level>{message}</level>",
    level=settings.log_level
)
logger.add(
    f"{settings.log_dir}/app_{{time:YYYY-MM-DD}}.log",
    rotation="00:00",
    retention="30 days",
    level=settings.log_level
)

# 创建FastAPI应用
app = FastAPI(
    title=settings.app_name,
    version=settings.app_version,
    description="人脸质量检测API服务 - 提供人脸检测、质量评估等功能"
)

# 配置CORS
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)


# ==================== 数据模型 ====================

class HealthResponse(BaseModel):
    """健康检查响应"""
    status: str
    version: str
    model_ready: bool
    timestamp: str


class FaceDetectionResponse(BaseModel):
    """人脸检测响应"""
    success: bool
    message: str
    data: Optional[dict] = None


class FaceDetectionRequest(BaseModel):
    """人脸检测请求参数"""
    min_face_size: Optional[int] = Field(None, description="最小人脸尺寸")
    max_angle: Optional[float] = Field(None, description="最大角度")
    blur_threshold: Optional[float] = Field(None, description="模糊阈值")
    min_quality_score: Optional[float] = Field(None, description="最低质量评分（0-1）")


# ==================== API 路由 ====================

@app.get("/", response_class=HTMLResponse)
async def root():
    """根路径 - 返回调试页面"""
    html_path = Path("static/debug.html")
    
    # 确保static目录存在
    Path("static").mkdir(exist_ok=True)
    
    if html_path.exists():
        logger.info(f"提供HTML页面: {html_path}")
        return html_path.read_text(encoding="utf-8")
    else:
        logger.warning(f"HTML文件不存在: {html_path}")
        return """
        <html>
            <head>
                <meta charset="UTF-8">
                <title>人脸质量检测API</title>
            </head>
            <body>
                <h1>人脸质量检测API服务</h1>
                <p>API文档: <a href="/docs">/docs</a></p>
                <p>健康检查: <a href="/health">/health</a></p>
                <p>⚠️ 调试页面未找到，请检查 static/debug.html 文件</p>
            </body>
        </html>
        """


@app.get("/health", response_model=HealthResponse)
async def health_check():
    """健康检查接口"""
    return HealthResponse(
        status="healthy",
        version=settings.app_version,
        model_ready=model_manager.is_ready,
        timestamp=datetime.now().isoformat()
    )


@app.get("/model/info")
async def get_model_info():
    """获取模型信息"""
    return model_manager.get_model_info()


@app.post("/detect", response_model=FaceDetectionResponse)
async def detect_face_quality(
    file: UploadFile = File(..., description="上传的图片文件"),
    min_face_size: Optional[int] = Form(None, description="最小人脸尺寸（像素）"),
    max_angle: Optional[float] = Form(None, description="最大姿态角度"),
    blur_threshold: Optional[float] = Form(None, description="清晰度阈值"),
    min_quality_score: Optional[float] = Form(None, description="最低质量评分（0-1）")
):
    """
    检测人脸质量
    
    上传图片文件，返回人脸质量检测结果
    """
    try:
        # 验证文件类型
        file_ext = Path(file.filename).suffix.lower()
        if file_ext not in settings.allowed_extensions:
            raise HTTPException(
                status_code=400,
                detail=f"不支持的文件格式。允许的格式: {settings.allowed_extensions}"
            )
        
        # 读取文件内容
        contents = await file.read()
        
        # 验证文件大小
        if len(contents) > settings.max_file_size:
            raise HTTPException(
                status_code=400,
                detail=f"文件太大。最大允许: {settings.max_file_size / 1024 / 1024}MB"
            )
        
        # 执行检测
        success, message, details = face_detector.detect_from_bytes(
            contents,
            min_face_size=min_face_size,
            max_angle=max_angle,
            blur_threshold=blur_threshold,
            min_quality_score=min_quality_score
        )
        
        logger.info(f"检测结果: {message} | 文件: {file.filename}")
        
        return FaceDetectionResponse(
            success=success,
            message=message,
            data=details
        )
        
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"检测过程出错: {e}")
        raise HTTPException(status_code=500, detail=f"服务器错误: {str(e)}")


@app.post("/detect/url")
async def detect_face_quality_from_url(
    url: str = Form(..., description="图片URL地址"),
    min_face_size: Optional[int] = Form(None),
    max_angle: Optional[float] = Form(None),
    blur_threshold: Optional[float] = Form(None),
    min_quality_score: Optional[float] = Form(None)
):
    """
    从URL检测人脸质量
    """
    import httpx
    
    try:
        async with httpx.AsyncClient(timeout=10.0) as client:
            response = await client.get(url)
            response.raise_for_status()
            
            contents = response.content
            
            if len(contents) > settings.max_file_size:
                raise HTTPException(
                    status_code=400,
                    detail=f"文件太大。最大允许: {settings.max_file_size / 1024 / 1024}MB"
                )
            
            success, message, details = face_detector.detect_from_bytes(
                contents,
                min_face_size=min_face_size,
                max_angle=max_angle,
                blur_threshold=blur_threshold,
                min_quality_score=min_quality_score
            )
            
            logger.info(f"URL检测结果: {message} | URL: {url}")
            
            return FaceDetectionResponse(
                success=success,
                message=message,
                data=details
            )
            
    except httpx.HTTPError as e:
        raise HTTPException(status_code=400, detail=f"无法下载图片: {str(e)}")
    except Exception as e:
        logger.error(f"URL检测出错: {e}")
        raise HTTPException(status_code=500, detail=f"服务器错误: {str(e)}")


@app.get("/config")
async def get_config():
    """获取当前配置"""
    return {
        "model_name": settings.model_name,
        "min_face_size": settings.min_face_size,
        "max_angle": settings.max_angle,
        "blur_threshold": settings.blur_threshold,
        "min_quality_score": settings.min_quality_score,
        "max_file_size_mb": settings.max_file_size / 1024 / 1024,
        "allowed_extensions": settings.allowed_extensions
    }


# ==================== 启动事件 ====================

@app.on_event("startup")
async def startup_event():
    """应用启动时执行"""
    logger.info(f"🚀 {settings.app_name} v{settings.app_version} 启动中...")
    logger.info(f"📦 模型目录: {settings.model_dir}")
    logger.info(f"📁 上传目录: {settings.upload_dir}")
    
    # 确保模型已加载
    if not model_manager.is_ready:
        logger.warning("模型未就绪，正在加载...")
    else:
        logger.info("✅ 模型已就绪")


@app.on_event("shutdown")
async def shutdown_event():
    """应用关闭时执行"""
    logger.info("👋 应用正在关闭...")


if __name__ == "__main__":
    import uvicorn
    
    uvicorn.run(
        "api:app",
        host=settings.host,
        port=settings.port,
        reload=settings.debug,
        log_level=settings.log_level.lower()
    )

